package ru.averta.notes.service.tag;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ru.averta.notes.dao.TagConnectorDao;
import ru.averta.notes.dao.TagDao;
import ru.averta.notes.domain.Site;
import ru.averta.notes.domain.Tag;
import ru.averta.notes.domain.TagConnector;
import ru.averta.notes.domain.User;
import ru.averta.notes.service.security.SecurityService;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

@Service
public class TagManagerImpl implements TagManager {

    private static final Logger logger = LoggerFactory.getLogger(TagManagerImpl.class);

    @Autowired private TagConnectorDao tagConnectorDao;
    @Autowired private TagDao tagDao;
    @Autowired private SecurityService security;

    @Override
    public List<Tag> getTagsForObject(Site object) {
        // TODO Сделать кеширование
        return findTagsForObject(object);
    }
    
    @Override
    public boolean hasTag(Site object, String tagTitle) {
        Tag tag = findTagByUserAndTitle(object.getUser(), tagTitle);
        return isObjectHasTag(object, tag);
    }

    @Override
    public Collection<Tag> findTitleByTitleAndCUser(String title) {
        return tagDao.findByTitleAndUser(title, security.getCurrentUser());
    }

    @Override public Collection<TagConnector> findTagConnectorsByCUser() {
        return tagConnectorDao.findByUser(security.getCurrentUser());
    }

    @Override public Collection<String> findTagsByCUser() {
        //todo закешировать метод
        return tagDao.findTagsByUser(security.getCurrentUser());
    }

    @Override
    public TagManager addTag(Site object, String tagTitle) {
        Tag tag = findTagByUserAndTitle(object.getUser(), tagTitle);
        if (!isObjectHasTag(object, tag)) {
            TagConnector connector = new TagConnector(object, tag);

            //Связываем
            tag.getTagConnectors().add(connector);

            tag.increaseCount();
            tagDao.save(tag);
            tagConnectorDao.save(connector);

            logger.debug("Зарегистрировали тег {} для объекта {}", tag.getTitle(), object);
        }

        return this;
    }

    @Override
    public TagManager removeTag(Site object, String tagTitle) {
        Tag tag = findTagByUserAndTitle(object.getUser(), tagTitle);
        return removeTag(object, tag);
    }

    @Override
    public TagManager removeTag(Site object, Tag tag) {
        if (isObjectHasTag(object, tag)) {
            TagConnector connector = getConnectorFor(object, tag);

            //Отвязываем
            tag.getTagConnectors().remove(connector);

            tag.decreaseCount();
            tagConnectorDao.remove(connector);
            if (tag.getCount() == 0) {
                tagDao.remove(tag);
                logger.debug("Удалили тег {} у объекта {}", tag.getTitle(), object);
            }
        }
        return this;
    }

    private Tag findTagByUserAndTitle(User user, String title) {
        Tag tag = tagDao.findByUserAndTitle(user, title);
        if (tag == null) {
            return new Tag(user, title);
        } else {
            return tag;
        }
    }

    private boolean isObjectHasTag(Site object, Tag tag) {
        return (getConnectorFor(object, tag) != null);
    }

    private List<Tag> findTagsForObject(Site object) {

        List<Tag> tags = new LinkedList<Tag>();
        Collection<TagConnector> connectors = tagConnectorDao.findByObject(object);

        for (TagConnector connector : connectors) {
            tags.add(connector.getTag());
        }

        return tags;
    }

    private TagConnector getConnectorFor(Site object, Tag tag) {
        TagConnector connector = tagConnectorDao.findByObjectAndTag(object, tag);
        return connector;
    }
}
